/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_redirect.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2014/09/29 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frcomm.h"
#include "frstr.h"
#include "frlog.h"
#include "frsutl.h"

#include "conntrack.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frexp_comm.h"

#include "../ora_core.h"
#include "../comm/ora_comm.h"
#include "ora_redirect.h"

#define ORA_REDIRECT_HOST "ADDRESS.HOST"
#define ORA_REDIRECT_PORT "ADDRESS.PORT"

extern void *g_p_apm_context;

/*******************************************************************************
*  FUNC     :  解析redirect包，格式形如 (ADDRESS=(PROTOCOL=tcp)(HOST=172.16.0.74)(PORT=4202))
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_hash_report                    (数据上报)
*           :  *p_st_packet                        (协议分析入力数据)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_redirect_unpack(Conntrack *p_st_conn
                        , L7session_ora *p_st_sess
                        , L7_ora_packet *p_st_ora_packet
                        , Frhash_header *p_st_hash_report
                        , Apm_packet *p_st_packet)
{
    unsigned short us_redirect_data_len;             // redirect data length
    char *p_redirect_data_str = NULL;
    Frstr *p_ancestor_keys = NULL;
    Frlist_header *p_st_head = NULL;
    char *p_redirect_host = NULL;
    char *p_redirect_port = NULL;

    bytebuff_setPosition(p_st_ora_packet->p_st_packet, APM_ORA_PKT_HEADER_LEN);      // 跳过包头

    if (bytebuff_get_short(p_st_ora_packet->p_st_packet, 2, &us_redirect_data_len, BYTE_BIG_ENDIAN) != FR_SUCC)
        goto error;

    if ((p_redirect_data_str = (char *) ora_malloc((us_redirect_data_len + 1) * sizeof(char), bytebuff_remaining(p_st_ora_packet->p_st_packet) + 1)) == NULL)
    {
        ORA_MALLOCK_ERR;
        goto error;
    }
    if (bytebuff_get_bytes_at(p_st_ora_packet->p_st_packet, APM_ORA_PKT_HEADER_LEN + 2, us_redirect_data_len, p_redirect_data_str) != FR_SUCC)
        goto error;
    p_redirect_data_str[us_redirect_data_len] = '\0';

    p_st_head = frlist_create();
    if (ora_NVPair_parser(p_redirect_data_str, us_redirect_data_len + 1, p_st_head, p_ancestor_keys) != FR_SUCC)
        goto error;

    // TODO: 判断p_redirect_host是不是IP地址

    // 取重定向的IP地址
    if (ora_NVPair_get_value(p_st_head, ORA_REDIRECT_HOST, &p_redirect_host) != FR_SUCC)
        goto error;

    // 取重定向的PORT端口
    if (ora_NVPair_get_value(p_st_head, ORA_REDIRECT_PORT, &p_redirect_port) != FR_SUCC)
        goto error;

    // 设置关联链路信息
    if (frexpect_add(g_p_apm_context, IPPROTO_TCP, iptools_parse_ipaddr(p_redirect_host), atoi(p_redirect_port), p_st_conn) != FR_SUCC)
        goto error;

    // 上报关联链路信息
//    if (frreport_add_conn_expect(p_st_hash_report, IPPROTO_TCP, p_st_packet->dst_ip, p_st_packet->src_ip,
//            p_st_packet->src_port, iptools_parse_ipaddr(p_redirect_host), atoi(p_redirect_port), p_st_ora_packet->st_timestamp_first) != FR_SUCC)
//        goto error;

    frlist_destroy(p_st_head, ora_NVPair_list_node_free);

    ora_free((void **) &p_redirect_data_str);
    return FR_SUCC;
error:
    ora_free((void **) &p_redirect_data_str);
    frlist_destroy(p_st_head, ora_NVPair_list_node_free);
    return FR_FAIL;
}
